/***************************************************************************
 *            modelica-grammar.hpp
 *
 *  Sat Mar 14 21:50:13 2009
 *  Copyright  2009  Jorge Eduardo Cardona Gaviria
 *  <jorgeecardona@gmail.com>
 ****************************************************************************/

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */
 
#ifndef _MODELICA_GRAMMAR_HPP_
#define _MODELICA_GRAMMAR_HPP_

//#define PHOENIX_LIMIT 10
//#define BOOST_SPIRIT_CLOSURE_LIMIT 10

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
//#include <boost/lambda/lambda.hpp>
//#include <boost/bind.hpp>
#include <boost/spirit/include/phoenix.hpp>



#include "modelica.hpp"

#include <gtkmm.h>
#include <iostream>
#include <string>
#include <fstream>

using namespace boost::phoenix;
using namespace boost::spirit;
using namespace boost::spirit::qi;
using namespace boost::spirit::ascii;
using namespace boost::spirit::arg_names;
//using boost::bind;

bool read_string(string content);
/*
struct push_back_impl
{
    template <typename Container, typename Item>
    struct result
    {
        typedef void type;
    };

    template <typename Container, typename Item>
    void operator()(Container& c, Item const& item) const
    {
        c.push_back(item);
    }
};

function<push_back_impl> const push_back = push_back_impl();**/


/*

struct root_closure : BOOST_SPIRIT_CLASSIC_NS::closure<root_closure, ModelicaStoredDefinition>
{
	// Return value.
	member1 r;
};

struct stored_definition_closure : BOOST_SPIRIT_CLASSIC_NS::closure< stored_definition_closure, ModelicaStoredDefinition, string, vector<ModelicaClassDefinition> >
{
	// Return Value
	member1 r; 

	// Fields
	member2 within;
	member3 classes;
};*/

/*struct class_definition_closure : BOOST_SPIRIT_CLASSIC_NS::closure<class_definition_closure, Modelica::Class*, bool, bool, Modelica::Class>
{
	// Return value
	member1 val;

	member2 encapsulated;
	member3 partial;

	member4 q;
};*/

/*struct class_specifier_closure : BOOST_SPIRIT_CLASSIC_NS::closure<class_specifier_closure, ModelicaClassSpecifier, string, ModelicaComposition>
{
	// Return value
	member1 r; 

	// Fields
	member2 name;
	member3 composition;
};  

struct composition_closure : BOOST_SPIRIT_CLASSIC_NS::closure<composition_closure, ModelicaComposition, vector<ModelicaElement>, vector<ModelicaElement>,vector<ModelicaElement>, string, string>
{
	// Return value
	member1 r;
	
	// Fields
	member2 elements;
	member3 public_elements;
	member4 protected_elements;
	member5 equation_section;
	member6 algorithm_section;
	
};

struct element_closure : BOOST_SPIRIT_CLASSIC_NS::closure<element_closure, ModelicaElement, string>
{
	// Return value
	member1 r;
	
	// Fields
	member2 content;
};

struct element_list_closure : BOOST_SPIRIT_CLASSIC_NS::closure<element_list_closure, vector<ModelicaElement> >
{
	// Return
	member1 r;
};
*/


template <typename Iterator>
struct ModelicaGrammar : grammar<Iterator, space_type>
{	
	ModelicaGrammar();

	symbols<char,unsigned>  KEYWORDS_TABLE;
/*
			add
				("algorithm", "algorithm")
				("and", "and")
				("annotation", "annotation")
				("assert", "assert")
				("block", "block")
				("break", "break")
				("class", "class")
				("connect", "connect")
				("connector", "connector")
				("constant", "constant")
				("constrainedby", "constrainedby")
				("der", "der")
				("discrete", "discrete")
				("each", "each")
				("else", "else")
				("elseif", "elseif")
				("elsewhen", "elsewhen")
				("encapsulated", "encapsulated")
				("end", "end")
				("enumeration", "enumeration")
				("equation", "equation")
				("expandable", "expandable")
				("extends", "extends")
				("external", "external")
				("false", "false")
				("final", "final")
				("flow", "flow")
				("for", "for")
				("function", "function")
				("import", "import")
				("if", "if")
				("in", "in")
				("initial", "initial")
				("inner", "inner")
				("input", "input")
				("loop", "loop")
				("model", "model")
				("not", "not")
				("or", "or")
				("outer", "outer")
				("output", "output")
				("package", "package")
				("parameter", "parameter")
				("partial", "partial")
				("protected", "protected")
				("public", "public")
				("record", "record")
				("redeclare", "redeclare")
				("replaceable", "replaceable")
				("return", "return")
				("then", "then")
				("true", "true")
				("type", "type")
				("when", "when")
				("while", "while")
				("within", "within")
			;
		}
	} KEYWORDS_TABLE;*/

    rule<Iterator, space_type>  KEYWORDS , K_ALGORITHM ,  K_AND ,  K_ANNOTATION ,  K_ASSERT ,  K_BLOCK ,  K_BREAK ,  K_CLASS ,  K_CONNECT ,  K_CONNECTOR ,  K_CONSTANT ,  K_CONSTRAINEDBY , 
                    K_DER ,  K_DISCRETE ,  K_EACH ,  K_ELSE ,  K_ELSEIF ,  K_ELSEWHEN ,  K_ENCAPSULATED ,  K_END ,  K_ENUMERATION ,  K_EQUATION ,  K_EXPANDABLE ,  
                    K_EXTENDS ,  K_EXTERNAL ,  K_FALSE ,  K_FINAL ,  K_FLOW ,  K_FOR ,  K_FUNCTION ,  K_IMPORT ,  K_IF ,  K_IN ,  K_INITIAL ,  K_INNER ,  K_INPUT ,  
                    K_LOOP ,  K_MODEL ,  K_NOT ,  K_OR ,  K_OUTER ,  K_OUTPUT ,  K_PACKAGE ,  K_PARAMETER ,  K_PARTIAL ,  K_PROTECTED ,  K_PUBLIC ,  K_RECORD ,  
                    K_REDECLARE ,  K_REPLACEABLE ,  K_RETURN ,  K_THEN ,  K_TRUE ,  K_TYPE ,  K_WHEN ,  K_WHILE ,  K_WITHIN,

                    // B.1
                    NONDIGIT, DIGIT, /*IDENT,*/ UNSIGNED_INTEGER, UNSIGNED_NUMBER, S_ESCAPE, S_CHAR, STRING, Q_CHAR, Q_IDENT,
                    
					// B.2.1    
            		stored_definition,
                    
					// B.2.2       
					/*class_definition, class_specifier,*/ base_prefix, enum_list, enumeration_literal, composition, language_specification, external_function_call, 
                    element_list, element, import_clause,
                    
					// B.2.3
                    extends_clause, constraining_clause,
                    
					// B.2.4
                    component_clause, type_prefix, type_specifier, component_list, component_declaration, conditional_attribute, declaration,
                    
					// B.2.5
                    modification, class_modification, argument_list, argument, element_modification_or_replaceable, element_modification, element_redeclaration, 
                    element_replaceable, component_clause1, component_declaration1,
                    
					// B.2.6
                    equation_section, algorithm_section, equation, statement, if_equation, if_statement, for_equation, for_statement, for_indices, for_index,
                    while_statement, when_equation, when_statement, connect_clause,
                    
					// B.2.7
                    expression, simple_expression, logical_expression, logical_term, logical_factor, relation, rel_op, arithmetic_expression, add_op, term, mul_op,
                    factor, primary, name, component_reference, function_call_args, function_arguments, named_arguments, named_argument, output_expression_list,
                    expression_list, array_subscripts, subscript, comment, string_comment, annotation;

	rule<Iterator, std::string(), space_type> IDENT;

	rule<Iterator, locals<Modelica::Class*,bool,bool>, space_type> class_definition;
	rule<Iterator, void(Modelica::Class*), space_type> class_specifier;

};

#endif /* _MODELICA_GRAMMAR_HPP_ */
